/* 
* Copyright (c) 2021 Talkweb Co.,ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. 
*/

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifi_device.h"

#include "lwip/netifapi.h"
#include "lwip/api_shell.h"

#include "wifi_connect_demo.h"

int g_wifiState = 0;

/**
 * @brief 打印WifiLinkedInfo信息
 * @param info 需要打印信息的WifiLinkedInfo指针
 */
static void PrintWifiLinkedInfo(WifiLinkedInfo *info)
{
    if (!info)
        return;

    static char macAddress[32] = {0};
    unsigned char *mac = info->bssid;
    snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X",
             mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

    printf("info: bssid: %s, rssi: %d, connState: %d, reason: %d, ssid: %s\r\n",
           macAddress, info->rssi, info->connState, info->disconnectedReason, info->ssid);
}

/**
 * @brief WiFi连接状态改变回调
 * @param state WiFi连接状态，参考WifiEventState
 * @param info WiFi连接信息
 */
static void OnWifiConnectionChanged(int state, WifiLinkedInfo *info)
{
    if (!info)
        return;

    printf("%s %d, state = %d \r\n", __FUNCTION__, __LINE__, state);
    PrintWifiLinkedInfo(info);

    g_wifiState = state;
}

/**
 * @brief WiFi扫描状态改变回调
 * @param state WiFi连接状态，参考WifiEventState
 * @param size
 */
static void OnWifiScanStateChanged(int state, int size)
{
    printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size);
}

/**
 * @brief 毫秒级延时
 * @param ms 需要延迟的毫秒数
 */
static void Delay(uint32_t ms)
{
    uint32_t usPerTicks = (1000 * 1000) / osKernelGetTickFreq();
    osDelay((ms * 1000) / usPerTicks);
    usleep((ms * 1000) % usPerTicks);
}

/**
 * @brief WiFi连接程序,CMSIS线程回调函数
 * @param arg 线程参数
 */
static void IotWifiConnectTask(void *arg)
{
    (void)arg;

    WifiErrorCode errCode;

    WifiEvent eventListener = {
        .OnWifiConnectionChanged = OnWifiConnectionChanged,
        .OnWifiScanStateChanged = OnWifiScanStateChanged};

    WifiDeviceConfig apConfig = {
        .ssid = DEFAILT_WIFI_SSID,
        .preSharedKey = DEFAILT_WIFI_PASSWORD,
        .securityType = WIFI_SEC_TYPE_PSK};

    Delay(10);

    errCode = RegisterWifiEvent(&eventListener);
    printf("RegisterWifiEvent errCode: %d\r\n", errCode);

    while (1)
    {
        int networkId = -1;
        //启动WiFi STA模式
        errCode = EnableWifi();
        printf("EnableWifi errCode: %d\r\n", errCode);
        Delay(100);

        errCode = AddDeviceConfig(&apConfig, &networkId);
        printf("AddDeviceConfig errCode: %d\r\n", errCode);

        g_wifiState = 0;
        errCode = ConnectTo(networkId);
        printf("ConnectTo(%d) errCode: %d\r\n", networkId, errCode);

        while (!g_wifiState)
        {
            Delay(10);
        }
        printf("g_wifiState: %d\r\n", g_wifiState);
        Delay(3000);

        // 联网业务开始
        // 这里是网络业务代码...
        struct netif *iface = netifapi_netif_find("wlan0");
        if (iface)
        {
            err_t ret = netifapi_dhcp_start(iface);
            printf("netifapi_dhcp_start: %d\r\n", ret);

            Delay(2000); // 等待DHCP服务分配IP地址

            ret = netifapi_netif_common(iface, dhcp_clients_info_show, NULL);
            printf("netifapi_netif_common: %d\r\n", ret);

            g_wifiState = WIFI_STATE_AVALIABLE;

            break;    //联网成功，退出循环
        }
        else
        {
            // 联网业务结束，断开和AP的连接
            Disconnect();
            RemoveDevice(networkId);

            //关闭WiFi STA模式
            errCode = DisableWifi();
            printf("DisableWifi errCode: %d\r\n", errCode);
            Delay(500);
        }
    }

    errCode = UnRegisterWifiEvent(&eventListener);
    printf("UnRegisterWifiEvent errCode: %d\r\n", errCode);
}

/**
 * @brief WiFi STA模式案例入口函数
 */
void IotWifiConnect(void)
{

    printf("\n\n entry wifi connect demo.\r\n");

    osThreadAttr_t attr;

    attr.name = "IotWifiConnectTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = osPriorityNormal;

    if (osThreadNew(IotWifiConnectTask, NULL, &attr) == NULL)
    {
        printf("[Talkweb Niobe] Falied to create IotWifiConnectTask!\n");
    }
}

APP_FEATURE_INIT(IotWifiConnect);
